#!/usr/bin/python                                                                                                                                                                                                    
# -*- coding:utf-8 -*-                                                                                                                                                                                               
from ConfigParser import RawConfigParser# Parser para archivos de configuración                                                                                                                                      
from os           import mkdir          # Crear directorios
from os           import environ        # Variables de ambiente del sistema
from os           import listdir        # Lista el contenido de un directorio
from os           import name as nomsis # Nombre del sistema operativo
from os.path      import join           # Unir dos rutas en una sola
from os.path      import exists         # Verifica si un archivo existe
from os.path      import abspath        # Calcular la ruta absoluta hacia una archivo
from os.path      import basename       # Obtener el nombre de una archivo a partir
                                        # de su ruta
from os.path       import isdir         # Verifica si un archivo es un directorio
from sys           import argv
from pygame.locals import *
from opencv        import adaptors
from opencv        import highgui,cv
import pygame
import Image
import opencv
import json # el módulo json (se projuncia "yei son") es una interfáz para el formato de
            # intercambio de datos JSON (JavaScript Object Notation) www.json.org
            # es un formato muy sencillo y permite mapear los datos directamente hacia
            # los objetos nativos de python: enteros, flotantes, listas, cadenas,
            # diccionarios, etc

def detectar(img,cascada,almacen,x,y,escala):
        cv.cvClearMemStorage(almacen)
        return cv.cvHaarDetectObjects(
                                   img,
                                   cascada,
                                   almacen,
                                   escala,
                                   2,
                                   0,
                                   cv.cvSize(x, y))

class Configuracion:

    def __init__(self):
        # Aquí se indica que el directorio de datos se encuentra en
        # $HOME/.refac/datos
        sdir = {
            #'posix' : join(environ['HOME'], '.refac' ),
            'posix' : abspath('.'),
            'nt'    : abspath('.')
        }
        self.sisdir = sdir[ nomsis ]
        self.datos  = join( self.sisdir, 'datos' )

conf = Configuracion()

capturando = False

class Individuo:
    """Representa una coleccion de imagenes correspondiente a la misma persona"""
    def __init__(self, ruta):
        """
        Crea un individuo nuevo

        @param ruta: Ubicación de los datos para el individuo, dentro del
        sistema de archivos.
        """

        if not exists( ruta ):
            mkdir( ruta )

        if ruta[-1] == '/':
            ruta = ruta[:-1]

        self.ruta = ruta

        self.nombre = basename(ruta)
        self.nomar  = "img%03d.pgm"

    def captura(self, ruta):
        """
        @param ruta: Carpeta de trabajo
        """

        capturando = True
        imgar = join( self.ruta, self.nomar )
        # Este objeto representa la cámara
        camara = highgui.cvCreateCameraCapture(0)
        fps = 30

        # Inicializa el módulo pygame
        pygame.init()

        # Crea una ventana de 320x240 pixeles
        ventana = pygame.display.set_mode((320,240))

        pygame.display.set_caption(
            "Proyecto de Investigación: Reconocimiento Facial")
        pantalla = pygame.display.get_surface()

        # Definiendo cuales son los archivos que describen los patrones
        # que se quieren reconocer
        #nombre_cascada ='./haarcascades/haarcascade_frontalface_alt.xml'
        nombre_cascada =join(ruta,
                'haarcascades/haarcascade_frontalface_alt.xml')

        # almacen es una especie de buffer (persistente)
        almacen = cv.cvCreateMemStorage(0)

        cascada = cv.cvLoadHaarClassifierCascade(nombre_cascada, cv.cvSize(14,14))
	

	escala = 2
        inx=0
        while inx < 1000: # Entra en un ciclo "infinito"
            try:
                msg = '[%03d] Capturando cuadro' % inx
                print '%-72s' % msg,
                img1 = highgui.cvQueryFrame(camara)
                print '[HECHO]'

		
            
                # Inicia la detección del rostro
                # Aquí hace una detección "general", es como si
                # el script dijera: "¡Hey, encontré algo!"
                msg = '[%03d] Detectando caras' % inx
                print '%-72s' % msg,
                caras = detectar(img1,cascada,almacen,50,50,escala)
                print '[HECHO]'
            

                if caras.total != 0:
                    print '[%03d] Se encontraron' % inx , caras.total, 'caras'
                    cara = caras[0]
                    cv.cvRectangle(img1,
                    cv.cvPoint( int(cara.x), int(cara.y)),
                    cv.cvPoint(int(cara.x + cara.width), int(cara.y + cara.height)),
                    cv.CV_RGB(255,0,0), 3, 8, 0)
                
                    # Encontrando la región de la imagen en que se detectó la cara
                    cara_x1 = int(cara.x + 2)/2
                    cara_y1 = int(cara.y + 2)/2
                    cara_x2 = int(cara.x + cara.width - 2)/2
                    cara_y2 = int(cara.y + cara.height - 2)/2

		else:
                    print '[%03d] No se reconicieron rostros' % inx
                
                img = adaptors.Ipl2PIL(img1).resize((320,240))

                #Si se detectó la cara entonces se puede guardar la imagen, 
                # con las indicaciones de los lugares en donde se encontraron los patrones.

                if caras.total:
                    #Seleccionar la región del rostro
                    box= (cara_x1, cara_y1 , cara_x2, cara_y2 )
                    imag= img.crop(box)
                
                    #Escalar la imagen
                    imag = imag.resize((70, 75), Image.ANTIALIAS)
                
                    #Covertir la imagen a escala de grises
                    imag = imag.convert ("L")
                
                    #Guardar la imagen
                    #imag.save('img/img'+str(inx)+'.pgm')
                    imag.save( imgar % inx )
                    inx+=1

                # Desplegando la imagen resultante
                pgimg = pygame.image.frombuffer(img.tostring(), img.size, img.mode)
                pantalla.blit(pgimg, (0,0))
                pygame.display.flip()
                pygame.time.delay(int(1000 * 1.0/fps))

		
			
            except Exception, e:
                print 'Ocurrio un error', e
                print e.message


        highgui.cvReleaseCapture(camara)
	pygame.quit()
	
  
	
	

    def capturar(self):
        """docstring for nvaImagen"""
        
        # Insertar código para caprutar, o llamar a la función

        imgar = join( self.ruta, self.nomar )
        for k in range(10):

            ind = imgar % k
            fp = open( ind, 'w' )
            json.dump(k, fp)
            fp.close()

            print 'Creando archivo:', ind

        # escribir la imagen en un archivo llamado: imgar % self.tam




class ImagDB:

    def __init__(self, nombre):
        """
        @param nombre: El nombre de la base de datos
        """
        self.nom  = nombre                     # Nombre de la base de datos
        self.ruta = join( conf.datos, nombre ) # Carpeta de la base de datos
        self.dbar = join( self.ruta, '.db' )   # archivo de configuración de la base de datos
        
        self.indnom = join(self.ruta, "img%d")   # Nombre para las carpetas de los individuos
        self.tam = 0        # Suponemos que la base de datos no tiene "registros"

        if not exists( self.ruta ):        # Si no existe la carpeta de la base de datos
            if not exists ( conf.datos ):
                if not exists ( conf.sisdir ):
                    mkdir (conf.sisdir)
                mkdir( conf.datos )

            mkdir ( self.ruta )            # creala
                                           # Obviamente no tiene individuos
                                           # Hay que llevar la cuenta de los
                                           # individuos agregados
            print self.ruta
        else:
            self.actualizar()

        self.guardar()
            
    def guardar(self):
        # Para guardar los datos en un archivo, se necesita un descriptor, el cual se obtiene
        # al abrir el archivo
        fp = open( self.dbar, 'w' ) # en este caso, como vamos a guardar el dato, abrimos el
                                    # archivo en modo escritura
        json.dump( self.tam, fp )   # Una vez que tenemos el archivo abierto, utilizando el
                                    # método json.dump, vaciamos el contenido de nuestra variable
                                    # en el archivo.
        fp.close()                  # Finalmente, enviamos los datos al disco duro, al cerrar el
                                    # archivo
        
    def actualizar(self):
        # Para guardar los datos en un archivo, se necesita un descriptor, el cual se obtiene
        # al abrir el archivo
        fp = open( self.dbar, 'r' ) # Ahora abrimos el archivo en modo lectura
        self.tam = json.load(fp)    # Leemos el contenido del archivo, y lo interpretamos hacia
                                    # el tipo de dato correspondiente, bueno, lo hace json por
                                    # nosotros :D. acto seguido, asignamos el resultado a nuestra
                                    # variable 
        fp.close()                  # Cerramos el archivo
    
    def agregar(self):
    
        # Para agregar un individuo, necesitamos crear la carpeta correspondiente, para lo cual
        # usamos la variable self.tam, que nos dice cuál es el número de darpeta que nos toca
        # crear. el formato para el nombre de la carpeta lo tenemos en la variable self.indnom
 
        inddir = self.indnom % self.tam  # Han que te ner cuidado si la numeración de las carpetas
                                         # empieza en cero o en uno.
                                         #
                                         # Suponiendo que self.tam vale, digamos, 5; entonces el
                                         # valor de inddir después de la asignación debe ser algo
                                         # así:
                                         #
                                         #   /home/diacus/.refac/datos/orldb/s5
                                         #
                                         # dentro de esta carpeta se almacenarán las fotografías del
                                         # siguiente individuo
                                         
        # llamar a la funcion para capturar imagenes

        while capturando:
            pass
        
        sujeto = Individuo( inddir )
        sujeto.captura(conf.sisdir) 
        
        self.tam += 1
        self.guardar()

def main(args):

    # blah, bla, bla
    #dbnom = argv[1]

    print 'Iniciando la creación de la base de datos:', args
    db = ImagDB(args)
    
    cont = True
    
    while cont:
        op = raw_input('Quieres agregar un individuo? (si) ')
        
        if op in ['', 'si', 's', 'SI']:
            db.agregar()
        elif op in ['no', 'NO', 'No', 'n', 'N' ]:
            cont = False
        else:
            print 'Error: Opción no válida'
            
if __name__ == '__main__':
    main()
